package org.example.controller;

import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.example.config.EsIndexUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;


/**
 * @description: TODO
 * @author 杨镇宇
 * @date 2024/7/6 13:17
 * @version 1.0
 */
@OpenAPIDefinition(
        info = @io.swagger.v3.oas.annotations.info.Info(
                title = "示例 API",
                version = "1.0",
                description = "这是一个示例 API 文档"
        ),
        tags = {
                @Tag(name = "Example", description = "查询文档")
        }
)
@RestController
@Slf4j
public class SelectController {


    @Resource
    private EsIndexUtils esIndexUtils;


    /**
     * 匹配查询
     * GET /blog_new/_search
     * {
     *   "query": {
     *     "match": {
     *       "author": "糖炒栗子"
     *     }
     *   },
     *   "size": 1000
     * }
     * @return
     */
    @GetMapping("/api/find_a")
    public void getA() {
        try {
            // 创建 SearchRequest 对象，指定索引名称
            SearchRequest searchRequest = new SearchRequest("blog_new");

            // 构建查询条件
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.query(QueryBuilders.matchQuery("author", "糖炒栗子"));
            searchSourceBuilder.size(1000);  // 设置返回结果数量
            // 将查询条件添加到 SearchRequest 对象中
            searchRequest.source(searchSourceBuilder);

            // 通过 esIndexUtils 工具类执行查询，假设你想使用默认的 ES 客户端
            SearchResponse response = esIndexUtils.queryRequest(searchRequest, "default");

            // 处理查询响应
            if (response != null && response.getHits().getTotalHits().value > 0) {
                response.getHits().forEach(hit -> {
                    log.info(hit.getSourceAsString()); // 打印每个文档的内容
                });
            } else {
                log.info("No results found.");
            }

        }catch (Exception e){
            log.error("错误",e);

        }
    }



    /**
     * 范围查询
     *      GET /blog_new/_search
     *     {
     *         "query": {
     *         "range": {
     *             "content": {
     *                 "gte": 100,
     *                  "lte": 120
     *             }
     *         }
     *     },
     *         "size": 1000
     *     }
     *
     * @return
     */
    @GetMapping("/api/find_b")
    public void getB() {
        try {
            // 创建 SearchRequest 对象，指定索引名称
            SearchRequest searchRequest = new SearchRequest("blog_new");

            // 构建查询条件
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.query(QueryBuilders.rangeQuery("content").gte(100).lte(120));
            searchSourceBuilder.size(1000);
            // 将查询条件添加到 SearchRequest 对象中
            searchRequest.source(searchSourceBuilder);

            // 通过 esIndexUtils 工具类执行查询，假设你想使用默认的 ES 客户端
            SearchResponse response = esIndexUtils.queryRequest(searchRequest, "default");

            // 处理查询响应
            if (response != null && response.getHits().getTotalHits().value > 0) {
                response.getHits().forEach(hit -> {
                    log.info(hit.getSourceAsString()); // 打印每个文档的内容
                });
            } else {
                log.info("No results found.");
            }

        }catch (Exception e){
            log.error("错误",e);

        }
    }



    /**
     * 布尔查询-分页查询
     *  match 查询
     *  用途：用于全文检索。match 查询会对搜索词进行分析（如分词、标准化），并与文档中经过分析的字段内容进行匹配
     *
     * 分页查询
     * 如果您想要获取第一页的结果，每页返回10个文档，您可以将"from"设置为0，
     *
     * "size"设置为10。如果想获取第二页的结果，您可以将"from"设置为10，"size"设置为10，以此类推。
     *
     *
     *
     * GET /blog_new/_search
     * {
     *   "query": {
     *     "bool": {
     *       "must": [
     *         { "match": { "title": "jstat命令查看jvm的GC信息2"  }},
     *         { "range": { "publish_date": { "gte": "2022-01-01" }}}
     *       ],
     *       "must_not": [
     *         { "range": { "content": { "gte": "300" }}}
     *       ],
     *       "should": [
     *         { "match": { "author": "yangzhenyu" }}
     *       ],
     *       "minimum_should_match": 1
     *     }
     *   },
     *   "from":0,
     *   "size": 1000
     * }
     * must: 查询条件必须满足：
     *
     * title字段必须包含“jstat命令查看jvm的GC信息2”。
     * publish_date字段的日期必须在2022年1月1日或之后。
     * must_not: 查询条件不能满足：
     *
     * content字段的值不能大于等于300。
     * should: 满足以下条件将提高文档的相关性：
     *
     * author字段如果包含“yangzhenyu”。
     * minimum_should_match: 至少需要满足一个should条件。
     *
     * from: 从结果的第0条开始返回。
     *
     * size: 返回的文档数量限制为1000条。
     * @return
     */
    @GetMapping("/api/find_c")
    public void getC() {
        try {
            // 创建 SearchRequest 对象，指定索引名称
            SearchRequest searchRequest = new SearchRequest("blog_new");

            // 构建查询条件
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
                    .must(QueryBuilders.matchQuery("title", "jstat命令查看jvm的GC信息2"))
                    .must(QueryBuilders.rangeQuery("publish_date").gte("2022-01-01"))
                    .mustNot(QueryBuilders.rangeQuery("content").gte(300))
                    .should(QueryBuilders.matchQuery("author", "yangzhenyu"))
                    .minimumShouldMatch(1);

            // 构建 SearchSourceBuilder
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.query(boolQuery);
            searchSourceBuilder.from(0);
            searchSourceBuilder.size(1000);
            searchRequest.source(searchSourceBuilder);

            // 通过 esIndexUtils 工具类执行查询，假设你想使用默认的 ES 客户端
            SearchResponse response = esIndexUtils.queryRequest(searchRequest, "default");

            // 处理查询响应
            if (response != null && response.getHits().getTotalHits().value > 0) {
                response.getHits().forEach(hit -> {
                    log.info(hit.getSourceAsString()); // 打印每个文档的内容
                });
            } else {
                log.info("No results found.");
            }

        }catch (Exception e){
            log.error("错误",e);

        }
    }



    /**
     * 布尔查询-分页查询
     *  term 精确匹配：term 查询用于精确匹配字段的内容，
     *  不进行分词。它适用于关键词或精确值的匹配，比如数值、日期、布尔值或者不需要分词的字符串（如ID、邮政编码）。
     *   用途：用于精确匹配。在搜索时，term 查询会查找完全与提供的值匹配的文档。通常用于 keyword 类型的字段或者数值字段。
     *  分页查询:
     * 如果您想要获取第一页的结果，每页返回10个文档，您可以将"from"设置为0，
     * "size"设置为10。如果想获取第二页的结果，您可以将"from"设置为10，"size"设置为10，以此类推。
     *
     *{
     *   "query": {
     *     "bool": {
     *       "must": [
     *         { "term": { "title.keyword": "jstat命令查看jvm的GC信息2" }},
     *         { "range": { "publish_date": { "gte": "2022-01-01" }}}
     *       ],
     *       "must_not": [
     *         { "range": { "content": { "gte": 300 }}}
     *       ],
     *       "should": [
     *         { "term": { "author.keyword": "yangzhenyu" }}
     *       ],
     *       "minimum_should_match": 1
     *     }
     *   },
     *   "from": 0,
     *   "size": 1000
     * }
     * must: 查询条件必须满足：
     *
     * title字段必须包含“jstat命令查看jvm的GC信息2”。
     * publish_date字段的日期必须在2022年1月1日或之后。
     * must_not: 查询条件不能满足：
     *
     * content字段的值不能大于等于300。
     * should: 满足以下条件将提高文档的相关性：
     *
     * author字段如果包含“yangzhenyu”。
     * minimum_should_match: 至少需要满足一个should条件。
     *
     * from: 从结果的第0条开始返回。
     *
     * size: 返回的文档数量限制为1000条。
     * @return
     */
    @GetMapping("/api/find_d")
    public void getD() {
        try {
            // 创建 SearchRequest 对象，指定索引名称
            SearchRequest searchRequest = new SearchRequest("blog_new");

            // 构建查询条件
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
                    .must(QueryBuilders.termQuery("title.keyword", "jstat命令查看jvm的GC信息2"))
                    .must(QueryBuilders.rangeQuery("publish_date").gte("2022-01-01"))
                    .mustNot(QueryBuilders.rangeQuery("content").gte(300))
                    .should(QueryBuilders.termQuery("author.keyword", "yangzhenyu"))
                    .minimumShouldMatch(1);

            // 构建 SearchSourceBuilder
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.query(boolQuery);
            searchSourceBuilder.from(0);
            searchSourceBuilder.size(1000);
            searchRequest.source(searchSourceBuilder);

            // 通过 esIndexUtils 工具类执行查询，假设你想使用默认的 ES 客户端
            SearchResponse response = esIndexUtils.queryRequest(searchRequest, "default");

            // 处理查询响应
            if (response != null && response.getHits().getTotalHits().value > 0) {
                response.getHits().forEach(hit -> {
                    log.info(hit.getSourceAsString()); // 打印每个文档的内容
                });
            } else {
                log.info("No results found.");
            }

        }catch (Exception e){
            log.error("错误",e);

        }
    }
}
